home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_313 / uucp / uucp1.lzh / src / uucico / gio.c < prev    next >
C/C++ Source or Header  |  1990-01-10  |  16KB  |  817 lines

  1.  
  2. /*
  3.  *  GIO.C    WINDOWED G PROTOCOL
  4.  *
  5.  *  Rewritten from scratch, except the checksum routine which was
  6.  *  rewritten but based on the old one.
  7.  *
  8.  *  WINDOW SIZE:    When changing the window size be sure there
  9.  *            are enough buffers available for pending txs.
  10.  *
  11.  *  GIO.C (c)Copyright 1989, Matthew Dillon, All Rights Reserved
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <exec/types.h>
  17. #include <proto/all.h>
  18.  
  19. void    FrameToPacket();
  20.  
  21. extern int debug;
  22. extern int WindowOne;
  23.  
  24. #define SUCCESS 0
  25. #define FAIL    1
  26.  
  27. #define MAGIC        0125252
  28. #define DLE        0x10
  29. #define WINDOWSIZE  2        /*  WindowSize = 1 or 2  */
  30. #define SEGSIZEK    2        /*  64 bytes ??     */
  31.  
  32. #define SUB1(var)   (((var)-1)&7)
  33.  
  34. typedef unsigned char    ubyte;
  35. typedef unsigned short    uword;
  36.  
  37. typedef struct {
  38.     ubyte   Dle;    /*  Literal ASCII DLE                */
  39.     ubyte   K;        /*  data size 2^(K+4) except K=0 means no data  */
  40.     ubyte   CL,CH;    /*  MAGIC - chksum(data) ^ C        */
  41.     ubyte   C;
  42.     ubyte   X;        /*  K ^ C0 ^ C1 ^ C            */
  43. } Frame;
  44.  
  45. typedef struct {
  46.     ubyte   CType;    /*  bits 7-6 of C    */
  47.     ubyte   CCmd;    /*  bits 5-3 of C    */
  48.     ubyte   CSeq;    /*  bits 2-0 of C    */
  49.     ubyte   PLen;    /*  pre-data (2 bytes) for SHORTDATA type */
  50.     ubyte   *Data;    /*  implies CType=LONGDATA or SHORTDATA */
  51.     uword   DLen;    /*  length of data    */
  52. } Packet;
  53.  
  54. #define CT_CONTROL    (0 << 6)
  55. #define CT_ALTCHN    (1 << 6)
  56. #define CT_LONGDATA    (2 << 6)
  57. #define CT_SHORTDATA    (3 << 6)
  58. #define CT_MASK     (3 << 6)
  59.  
  60. #define CC_CLOSE    (1 << 3)
  61. #define CC_RJ        (2 << 3)
  62. #define CC_SRJ        (3 << 3)
  63. #define CC_RR        (4 << 3)
  64. #define CC_INITC    (5 << 3)
  65. #define CC_INITB    (6 << 3)
  66. #define CC_INITA    (7 << 3)
  67. #define CC_MASK     (7 << 3)
  68.  
  69. #define SEQ_MASK    7
  70.  
  71. #define WAIT_ACK    1
  72. #define WAIT_DATA    2
  73. #define WAIT_CONTROL    3
  74.  
  75. #define MaxPktSize    4096
  76.  
  77. char    RxBuf[MaxPktSize+4];
  78. char    TxBuf[4][MaxPktSize+4];
  79.  
  80.                 /*  TRANSMIT STAGE        */
  81. char    TxSeq = 0;        /*  Last send packet        */
  82. char    TxPend= 0;        /*  hasn't been acked yet   */
  83. uword    TxWinSize;        /*  1 or 2            */
  84. uword    TxSegSize;        /*  maximum segment size    */
  85. char    TxSegK;         /*  K for TxSegSize        */
  86. Packet    TxPacket[8];        /*  contents of last packet */
  87.  
  88.                 /*  RECEIVE STAGE        */
  89. char    RxSeq = 1;        /*  Next expected recv pkt  */
  90. char    RxRdy = 0;        /*  Has come in..        */
  91. char    RxRetry = 4;
  92. char    RxNotAcked = 0;     /*  We have yet to ack it   */
  93. Packet    RxPacket;        /*  The packet that has come in */
  94.  
  95. /*
  96.  *  Get Transmit Buffer.  Note that some space to the left is available
  97.  */
  98.  
  99. char *
  100. GetTxBuf()
  101. {
  102.     static int index = 0;
  103.  
  104.     index = (index + 1) & 3;
  105.     return(TxBuf[index] + 2);
  106. }
  107.  
  108. int
  109. gwrdata(fi)
  110. FILE *fi;
  111. {
  112.     int bytes;
  113.     char *buf = GetTxBuf();
  114.  
  115.     if (debug > 7)
  116.     printf("GWRDATA: ");
  117.  
  118.     while ((bytes = fread(buf, 1, TxSegSize, fi)) >= 0) {
  119.     if (SendDataPacket(buf, bytes) != SUCCESS) {
  120.         if (debug > 7)
  121.         printf("GWR Failed\n");
  122.         return(FAIL);
  123.     }
  124.     if (debug > 7)
  125.         printf("\nGWROK ");
  126.     if (bytes == 0)
  127.         break;
  128.     buf = GetTxBuf();
  129.     }
  130.     if (debug > 7)
  131.     printf("\nGWFile Last Ack\n");
  132.     while (TxPend) {
  133.     if (GetData(WAIT_ACK, NULL) == FAIL)
  134.         return(FAIL);
  135.     }
  136.     return (SUCCESS);
  137. }
  138.  
  139. /*
  140.  *  Write message to the other guy.
  141.  *
  142.  *  NOTE: LONGDATA packets used exclusively and \0 fill to end.
  143.  */
  144.  
  145. int
  146. gwrmsg(str)
  147. char *str;
  148. {
  149.     int len = strlen(str) + 1;      /*  type + str + \0  */
  150.  
  151.     if (debug > 8)
  152.     printf("GWRMSG: %s\n", str);
  153.  
  154.     while (len > TxSegSize) {
  155.     char *buf = GetTxBuf();
  156.     movmem(str, buf, TxSegSize);
  157.     if (debug > 8)
  158.         printf("GWR-SEND %d\n", TxSegSize);
  159.     if (SendDataPacket(buf, TxSegSize) != SUCCESS)
  160.         return(FAIL);
  161.     len -= TxSegSize;
  162.     str += TxSegSize;
  163.     }
  164.  
  165.     /*
  166.      *    Find optimal packet size (remember, we must force LONGDATA
  167.      *
  168.      *    Apparently packet sizes less than the agreed upon size are
  169.      *    not allowed ???
  170.      */
  171.  
  172.     {
  173.     short siz = TxSegSize;
  174.     char *buf = GetTxBuf();
  175. #ifdef NOTDEF
  176.     short k = TxSegK;
  177.  
  178.     while (k > 1 && (siz >> 1) >= len) {
  179.         --k;
  180.         siz >>= 1;
  181.     }
  182. #endif
  183.     if (debug > 8)
  184.         printf("GWR-FNL %d %d\n", len, siz);
  185.  
  186.     movmem(str, buf, len);
  187.     setmem(buf + len, siz - len, 0);
  188.     if (SendDataPacket(buf, siz) != SUCCESS) {
  189.         if (debug > 8)
  190.         printf("GWR-FAIL\n");
  191.         return(FAIL);
  192.     }
  193.     }
  194.     if (debug > 8)
  195.     printf("GWR Last Ack\n");
  196.     while (TxPend) {
  197.     if (GetData(WAIT_ACK, NULL) == FAIL)
  198.         return(FAIL);
  199.     }
  200.     return (SUCCESS);
  201. }
  202.  
  203. int
  204. grddata(fi)
  205. FILE *fi;
  206. {
  207.     int bytes;
  208.     char *buf;
  209.  
  210.     if (debug > 7)
  211.     printf("GRDDATA\n");
  212.     while ((bytes = RecvDataPacket(&buf)) > 0) {
  213.     if (debug > 7)
  214.         printf("GRDDATA blk %d\n", bytes);
  215.     fwrite(buf, 1, bytes, fi);
  216.     }
  217.     if (debug > 7)
  218.     printf("GRDDATA end %d\n", bytes);
  219.     if (bytes < 0)
  220.     return(FAIL);
  221.     else
  222.     return(SUCCESS);
  223. }
  224.  
  225. grdmsg(buf, maxlen)
  226. char *buf;
  227. {
  228.     short i;
  229.     short n;
  230.     short slen;
  231.     char *ptr;
  232.  
  233.     i = 0;
  234.     if (debug > 8)
  235.     printf("GRDMSG\n");
  236.     while ((n = RecvDataPacket(&ptr)) > 0) {
  237.     ptr[n] = 0;
  238.     slen = strlen(ptr);
  239.     if (slen > maxlen - 1) {
  240.         printf("GRDMSG: Buffer overflow!\n");
  241.         return (FAIL);
  242.     }
  243.     movmem(ptr, buf + i, slen);
  244.     buf[i + slen] = 0;
  245.     if (slen != n)
  246.         break;
  247.     i += slen;
  248.     maxlen -= slen;
  249.     }
  250.     if (debug > 8)
  251.     printf("GRDMSGEND %d (%d) %s\n", n, i, buf);
  252.     if (n < 0) {
  253.     buf[0] = 0;
  254.     return(FAIL);
  255.     }
  256.     return(SUCCESS);
  257. }
  258.  
  259. SendDataPacket(buf, bytes)
  260. ubyte *buf;
  261. int bytes;
  262. {
  263.     Packet  P;
  264.  
  265.     /*
  266.      *    If window exhausted we must wait for at least one ack.
  267.      */
  268.  
  269.     if (TxPend == TxWinSize) {
  270.     if (GetData(WAIT_ACK, NULL) == FAIL)
  271.         return(FAIL);
  272.     }
  273.  
  274.     TxSeq = (TxSeq + 1) & 7;        /*  next Tx packet  */
  275.  
  276.     /*
  277.      *    Figure out best fit packet size.  Apparently packets smaller
  278.      *    then the agreed upon size are not allowed ???
  279.      */
  280.  
  281. #ifdef NOTDEF
  282.     {
  283.     short k = TxSegK;
  284.     P.DLen = TxSegSize;
  285.     while (k > 1 && P.DLen && (P.DLen >> 1) >= bytes) {
  286.         --k;
  287.         P.DLen >>= 1;
  288.     }
  289.     }
  290. #else
  291.     P.DLen = TxSegSize;
  292. #endif
  293.  
  294.     if (bytes < P.DLen) {
  295.     uword extra = P.DLen - bytes;
  296.     setmem(buf + bytes, extra, 0);
  297.     if (extra <= 127) {
  298.         P.PLen = 1;
  299.         buf[-1] = extra;
  300.     } else {
  301.         P.PLen = 2;
  302.         buf[-2] = 0x80 | extra;
  303.         buf[-1] = (extra >> 7);
  304.     }
  305.     P.CType = CT_SHORTDATA;
  306.     } else {
  307.     P.PLen = 0;
  308.     P.CType = CT_LONGDATA;
  309.     }
  310.     P.CCmd = TxSeq << 3;    /*  transmit sequence number */
  311.     P.CSeq = (RxSeq - 1) & 7;   /*  last valid received pkt  */
  312.     P.Data = buf;
  313.  
  314.     if (debug > 8)
  315.     printf("WRITE PACKET %d %d\n", TxSeq, P.CSeq);
  316.  
  317.     if (RxNotAcked)             /*  We've acked the rx packet */
  318.     RxNotAcked = 0;
  319.  
  320.     TxPacket[TxSeq & 7] = P;
  321.     ++TxPend;
  322.  
  323.     WritePacket(&TxPacket[TxSeq & 7], 1);
  324.  
  325.     return(SUCCESS);
  326. }
  327.  
  328. RecvDataPacket(pbuf)
  329. char **pbuf;
  330. {
  331.     if (RxRdy == 0) {
  332.     if (GetData(WAIT_DATA, NULL) != SUCCESS)
  333.         return(-1);
  334.     }
  335.     *pbuf = RxPacket.Data;
  336.     RxRdy = 0;
  337.     return((int)RxPacket.DLen);
  338. }
  339.  
  340. gturnon(master)
  341. {
  342.     Packet P;
  343.     short retry = 5;
  344.     short windowsize = WINDOWSIZE;    /*  our prefered window size */
  345.     short segsize = SEGSIZEK;        /*  our prefered segment size */
  346.  
  347.     if (WindowOne)
  348.     windowsize = 1;
  349.  
  350.     if (master) {
  351.     while (retry > 0) {
  352.         WriteCtlPacket(CC_INITA | windowsize);
  353.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
  354.         if (P.CSeq && P.CSeq < windowsize)
  355.             windowsize = P.CSeq;
  356.         break;
  357.         }
  358.         --retry;
  359.     }
  360.     while (retry > 0) {
  361.         WriteCtlPacket(CC_INITB | (segsize - 1));
  362.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
  363.         if (P.CSeq < segsize - 1)
  364.             segsize = P.CSeq + 1;
  365.         break;
  366.         }
  367.         --retry;
  368.     }
  369.     while (retry > 0) {
  370.         WriteCtlPacket(CC_INITC | windowsize);
  371.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
  372.         if (P.CSeq && P.CSeq < windowsize)
  373.             windowsize = P.CSeq;
  374.         break;
  375.         }
  376.         --retry;
  377.     }
  378.     } else {
  379.     while (retry > 0) {
  380.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
  381.         WriteCtlPacket(CC_INITA | windowsize);
  382.         if (P.CSeq && windowsize > P.CSeq)
  383.             windowsize = P.CSeq;
  384.         break;
  385.         }
  386.         --retry;
  387.     }
  388.     while (retry > 0) {
  389.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
  390.         WriteCtlPacket(CC_INITB | (segsize - 1));
  391.         if (P.CSeq < segsize - 1)
  392.             segsize = P.CSeq + 1;
  393.         break;
  394.         }
  395.         --retry;
  396.     }
  397.     while (retry > 0) {
  398.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
  399.         WriteCtlPacket(CC_INITC | windowsize);
  400.         if (P.CSeq && windowsize > P.CSeq)
  401.             windowsize = P.CSeq;
  402.         break;
  403.         }
  404.         --retry;
  405.     }
  406.     }
  407.     TxSegK = segsize;
  408.     TxSegSize = 1 << (TxSegK + 4);
  409.     TxWinSize = windowsize;
  410.     if (debug > 0)
  411.     printf("Window Size is %d\n", TxWinSize);
  412.     if (retry == 0)
  413.     return(FAIL);
  414.     return(SUCCESS);
  415. }
  416.  
  417. gturnoff()
  418. {
  419.     Packet P;
  420.  
  421.     WriteCtlPacket(CC_CLOSE);
  422.     if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_CLOSE) {
  423.     WriteCtlPacket(CC_RR | ((RxSeq - 1) & 7));
  424.     return (SUCCESS);
  425.     }
  426.     return (FAIL);
  427. }
  428.  
  429. GetData(waitfor, p)
  430. Packet *p;
  431. {
  432.     Packet P;
  433.     short timeout;
  434.  
  435.     /*
  436.      *    If we haven't acked the last packet we received we must do
  437.      *    so now before we can expect to receive another one!
  438.      */
  439.  
  440.     if (waitfor == WAIT_ACK)
  441.     timeout = 20;
  442.     else if (waitfor == WAIT_DATA)
  443.     timeout = 40;
  444.     else
  445.     timeout = 40;
  446.  
  447.     for (;;) {
  448.     if (RxNotAcked) {
  449.         WriteCtlPacket(CC_RR | SUB1(RxSeq));
  450.         RxNotAcked = 0;
  451.     }
  452.     if (ReadPacket(&P, timeout) == FAIL) {
  453.         if (waitfor == WAIT_DATA) {
  454.         if (RxRetry) {
  455.             --RxRetry;
  456.             if (debug > 8)
  457.             printf("\nWAIT-DATA, TIMEOUT, SEND RJ\n");
  458.             WriteCtlPacket(CC_RJ | SUB1(RxSeq));
  459.             continue;
  460.         }
  461.         }
  462.         if (waitfor == WAIT_ACK) {
  463.         if (RxRetry) {
  464.             --RxRetry;
  465.             if (debug > 8)
  466.             printf("\nWAIT-ACK, TIMEOUT, RETRY\n");
  467.             WritePacket(&TxPacket[(TxSeq - TxPend + 1) & 7], 1);
  468.             continue;
  469.         }
  470.         }
  471.         if (debug > 8)
  472.         printf("COMPLETE FAILURE RxRetry = %d\n", RxRetry);
  473.         return(FAIL);
  474.     }
  475.     RxRetry = 4;
  476.     switch(P.CType) {
  477.     case CT_CONTROL:
  478.         switch(P.CCmd) {
  479.         case CC_CLOSE:  /*    End of communication ... not an ACK!       */
  480.         if (waitfor == WAIT_CONTROL) {
  481.             *p = P;
  482.             return(SUCCESS);
  483.         }
  484.         return(FAIL);
  485.         case CC_RJ:     /*    Reject packet (P.CSeq == last good packet) */
  486.                 /*    resend last packet  */
  487.  
  488.         WritePacket(&TxPacket[(P.CSeq + 1) & 7], 1);
  489.         {
  490.             short i;
  491.             for (i = 0; i < TxPend; ++i) {
  492.             if (P.CSeq == ((TxSeq - i) & 7))
  493.                 break;
  494.             }
  495.             if (i == TxPend)
  496.             printf("RJ, bad seq no: %d expected %d-%d\n", P.CSeq, (TxSeq - TxPend + 1) & 7, TxSeq);
  497.         }
  498.         break;
  499.         case CC_SRJ:    /*    Selective Reject (P.CSeq == bad packet # ) */
  500.         return(FAIL);
  501.         case CC_RR:     /*    Ack to packet  (P.CSeq == packet # acked)   */
  502.         if (RecvdAck(P.CSeq) == SUCCESS && waitfor == WAIT_ACK)
  503.             return(SUCCESS);
  504.         break;
  505.         case CC_INITC:
  506.         case CC_INITB:
  507.         case CC_INITA:
  508.         if (waitfor == WAIT_CONTROL) {
  509.             *p = P;
  510.             return(SUCCESS);
  511.         }
  512.         return(FAIL);
  513.         }
  514.         break;
  515.     case CT_ALTCHN:
  516.         printf("ALTCHN packet ??\n");
  517.         break;
  518.     case CT_LONGDATA:
  519.     case CT_SHORTDATA:
  520.         {
  521.         char rxseq = P.CCmd >> 3;
  522.         char txack = P.CSeq;
  523.  
  524.         if (RxRdy == 1) {
  525.             printf("Got two receive packets without me acking!\n");
  526.         }
  527.         if (rxseq == SUB1(RxSeq)) {
  528.             RxNotAcked = 1;
  529.             continue;        /*    ignore resent pkts we already have */
  530.         } else if (rxseq != RxSeq) {
  531.             if (rxseq == ((RxSeq + 1) & 7))     /*  missed one (windowed)   */
  532.             WriteCtlPacket(CC_RJ | SUB1(RxSeq));
  533.             printf("Received sequence %d, expected %d\n", rxseq, RxSeq);
  534.             break;
  535.         } else {
  536.             if (debug > 6)
  537.             printf("RECV SEQUENCE %d\n", rxseq);
  538.         }
  539.  
  540.         RecvdAck(txack);
  541.  
  542.         /*
  543.          *  Delay sending the ACK back in case we can combine
  544.          *  it with the next transmitted packet.
  545.          */
  546.  
  547.         RxNotAcked = 1;     /*  we haven't ack'd the rx packet */
  548.  
  549.         RxSeq = (RxSeq + 1) & 7;
  550.         RxRdy = 1;
  551.         RxPacket = P;
  552.         if (waitfor == WAIT_DATA)
  553.             return(SUCCESS);
  554.         if (TxPend == 0 && waitfor == WAIT_ACK)
  555.             return(SUCCESS);
  556.         }
  557.         break;
  558.     }
  559.     }
  560. }
  561.  
  562. RecvdAck(seq)
  563. char seq;
  564. {
  565.     short i;
  566.     short seqbase = TxSeq - TxPend + 1;
  567.  
  568.     /*
  569.      *  which packet was acked?
  570.      */
  571.  
  572.     for (i = 0; i < TxPend; ++i) {
  573.     if (seq == ((seqbase + i) & 7))
  574.         break;
  575.     }
  576.     if (i == TxPend) {
  577.     if (TxPend)
  578.         printf("He acked the wrong packet! %d expected %d\n", seq, TxSeq);
  579.     return(FAIL);
  580.     }
  581.     if (debug > 8)
  582.     printf("TxPend %d ->", TxPend);
  583.     TxPend = TxPend - i - 1;
  584.     if (debug > 8)
  585.     printf(" %d\n", TxPend);
  586.     return(SUCCESS);
  587. }
  588.  
  589. WriteCtlPacket(cc)
  590. {
  591.     Packet pk;
  592.  
  593.     pk.CType = CT_CONTROL;
  594.     pk.CCmd  = cc & CC_MASK;
  595.     pk.CSeq  = cc & SEQ_MASK;
  596.     pk.PLen  = 0;
  597.     pk.DLen  = 0;
  598.     WritePacket(&pk, 0);
  599.     return(SUCCESS);
  600. }
  601.  
  602. WritePacket(pk, async)
  603. Packet *pk;
  604. {
  605.     Frame   F;
  606.     uword   sum;
  607.  
  608.     F.Dle = DLE;
  609.     F.C   = pk->CType | pk->CCmd | pk->CSeq;
  610.     F.K   = 9;
  611.  
  612.     if (pk->CType == CT_SHORTDATA || pk->CType == CT_LONGDATA)
  613.     F.K = LenToK(pk->DLen);
  614.     else
  615.     pk->DLen = 0;
  616.  
  617.     sum = MAGIC - (CheckSum(pk->Data - pk->PLen, pk->DLen) ^ F.C);
  618.  
  619.     F.CH  = sum >> 8;
  620.     F.CL  = sum;
  621.     F.X   = F.K ^ F.CH ^ F.CL ^ F.C;
  622.  
  623.     if (debug > 8)
  624.     printf("WritePacket: F.K = %d F.C = %02x\n", F.K, F.C);
  625.  
  626.     if (async)
  627.     xwritea(&F, sizeof(F));
  628.     else
  629.     xwrite(&F, sizeof(F));      /*  write header    */
  630.     if (pk->DLen) {             /*  write data      */
  631.     if (async)
  632.         xwritea(pk->Data - pk->PLen, pk->DLen);
  633.     else
  634.         xwrite(pk->Data - pk->PLen, pk->DLen);
  635.     }
  636.     return(SUCCESS);
  637. }
  638.  
  639. ReadPacket(pk, timeout)
  640. Packet *pk;
  641. {
  642.     Frame   F;
  643.     short   c;
  644.     short   i = 0;
  645.  
  646.     pk->Data = RxBuf;
  647.     pk->CType = 0xFF;
  648.     pk->CCmd  = 0;
  649.     pk->CSeq  = 0;
  650.  
  651.     if (debug > 8)
  652.     printf("ReadPacket\n");
  653.     while ((c = xgetc(timeout)) != EOF) {
  654.     if (debug > 8)
  655.         printf("RP %d %02x\n", i, c);
  656.  
  657.     switch(i) {
  658.     case 0:
  659.         if (c == DLE) {
  660.         F.Dle = c;
  661.         ++i;
  662.         }
  663.         break;
  664.     case 1:
  665.         F.K = c;
  666.         ++i;
  667.         if (c == DLE) { /*  K only valid 0-9    */
  668.         F.Dle = c;
  669.         i = 1;
  670.         }
  671.         break;
  672.     case 2:
  673.         F.CL = c;
  674.         ++i;
  675.         break;
  676.     case 3:
  677.         F.CH = c;
  678.         ++i;
  679.         break;
  680.     case 4:
  681.         F.C = c;
  682.         ++i;
  683.         break;
  684.     case 5:
  685.         F.X = c;
  686.         if (F.X != (F.K ^ F.CH ^ F.CL ^ F.C)) {
  687.         printf("F.X failed: %02x %02x\n", F.X, (F.K ^ F.CH ^ F.CL ^ F.C));
  688.         i = 0;
  689.         } else {        /*    get data segment if any */
  690.         ++i;
  691.         }
  692.         break;
  693.     }
  694.     if (i == 6)
  695.         break;
  696.     }
  697.     if (debug > 8)
  698.     printf("RP Hdr i = %d, F.K = %d F.C = %02x\n", i, F.K, F.C);
  699.  
  700.     if (i == 6) {       /*  Receive Data Portion    */
  701.     uword pktsize = 1 << (F.K + 4);
  702.     uword n;
  703.  
  704.     if (F.K == 0 || F.K == 9)
  705.         pktsize = 0;        /*    FIXME is K=0 an illegal case? */
  706.  
  707.     if (pktsize > MaxPktSize) {
  708.         printf("Protocol failure pktsize %d/%d/%d\n", pktsize, TxSegSize, MaxPktSize);
  709.         return (FAIL);
  710.     }
  711.     for (n = 0; n < pktsize; ++n) {
  712.         if ((c = xgetc(4)) == EOF)
  713.         break;
  714.         pk->Data[n] = c;
  715.     }
  716.     if (c != EOF) {
  717.         uword hissum;
  718.         uword oursum;
  719.         hissum = (F.CH << 8) | F.CL;
  720.         oursum = MAGIC - (CheckSum(pk->Data, pktsize) ^ F.C);
  721.         if (debug > 8)
  722.         printf("Got Data, checking: %04x %04x\n", hissum, oursum);
  723.         if (hissum == oursum) {
  724.         FrameToPacket(&F, pk, pk->Data);
  725.         return (SUCCESS);
  726.         }
  727.     } else {
  728.         FrameToPacket(&F, pk, pk->Data);    /* mainly for pk->CType */
  729.         return (FAIL);
  730.     }
  731.     }
  732.     /*
  733.      *    Timeout, retry?
  734.      */
  735.     return (FAIL);
  736. }
  737.  
  738. CheckSum(s, n)
  739. ubyte *s;
  740. int n;
  741. {
  742.     uword sum;
  743.     uword x;
  744.     uword t;
  745.  
  746.     if (n == 0)
  747.     return(0);
  748.     sum = -1;
  749.     x = 0;
  750.  
  751.     while (n) {
  752.     if (sum & 0x8000)
  753.         sum = (sum << 1) | 1;
  754.     else
  755.         sum = (sum << 1);
  756.  
  757.     t = sum;
  758.     sum += *s++;
  759.     x += sum ^ n;
  760.     if (sum <= t)
  761.         sum ^= x;
  762.     --n;
  763.     }
  764.     return((int)sum);
  765. }
  766.  
  767. void
  768. FrameToPacket(fr, pk, data)
  769. Frame *fr;
  770. Packet *pk;
  771. ubyte *data;
  772. {
  773.     pk->CType = fr->C & CT_MASK;
  774.     pk->CCmd  = fr->C & CC_MASK;
  775.     pk->CSeq  = fr->C & SEQ_MASK;
  776.     switch(pk->CType) {
  777.     case CT_LONGDATA:
  778.     pk->DLen = 1 << (fr->K + 4);
  779.     break;
  780.     case CT_SHORTDATA:
  781.     pk->DLen = 1 << (fr->K + 4);
  782.     if (pk->Data[0] & 0x80) {
  783.         pk->DLen -= (pk->Data[0] & 0x7F) | (pk->Data[1] << 7);
  784.         if (pk->DLen < 0) {
  785.         printf("DLEN ERROR %d\n", pk->DLen);
  786.         pk->DLen = 0;
  787.         }
  788.         pk->Data += 2;
  789.     } else {
  790.         pk->DLen -= *pk->Data;
  791.         ++pk->Data;
  792.     }
  793.     break;
  794.     default:
  795.     pk->DLen = 0;
  796.     break;
  797.     }
  798. }
  799.  
  800. LenToK(bytes)
  801. uword bytes;
  802. {
  803.     uword n = 32;
  804.     uword k = 1;
  805.  
  806.     while (n < bytes) {
  807.     n <<= 1;
  808.     ++k;
  809.     }
  810.     if (k > 8) {
  811.     printf("Soft error, LenToK: %d %d %d\n", bytes, n, k);
  812.     k = 8;
  813.     }
  814.     return((int)k);
  815. }
  816.  
  817.